﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using System.Web.UI.WebControls;
using eBusiness.App_DAL;
using eBusiness.Models;

namespace eBusiness.Controllers
{ 
    public class ProductController : Controller
    {
        private readonly UnitOfWork _unitOfWork = new UnitOfWork();

        //
        // GET: /Product/

        public ViewResult Index(Product filter = null, int? pageNumber = 1, int? pageSize = 5, byte? categoryId = null, string softField = "CreatedDate", string softDir = "Desc", string viewType = "List")
        {
            //set current variable for filter

            ViewBag.CurrentCategoryID = Session["Category"] = categoryId.ToString();
            if (filter != null) ViewBag.CurrentStatusID = Session["StatusID"] = filter.StatusID.ToString();
            ViewBag.CurrentSoftField = softField;
            ViewBag.CurrentSoftDir = softDir;
            ViewBag.CurrentSoftDir = viewType;
            ViewBag.CurrentIsApproved = filter != null && filter.IsApproved;
            ViewBag.CurrentIsHot = filter != null && filter.IsHot;
            ViewBag.CurrentIsHomepage = filter != null && filter.IsHomepage;
            ViewBag.CurrentIsDiscount = filter != null && filter.IsDiscount;

            //reset data for dropdownlist for category, status, soft field and sorf directory

            //ViewBag.Categories = new SelectList(_unitOfWork.CategoryRepository.Get(c => c.IsDeleted == false), "ID", "Name", Session["Category"]);
            ViewBag.StatusId = new SelectList(_unitOfWork.StatusRepository.Get(s => s.IsDeleted == false), "ID", "Name", Session["StatusID"]);
            var softdir = new List<ListItem> { new ListItem("Desc", "DESC"), new ListItem("Asc", "ASC") };
            //ViewBag.SoftDir = new SelectList(softdir, Session["SoftDir"]);
            ViewBag.SoftDir = new SelectList(softdir, softDir);

            var viewTypes = new List<ListItem> { new ListItem("List", "List"), new ListItem("Grid", "List") };
            ViewBag.ViewType = new SelectList(viewTypes, viewType);

            var softFields = new List<ListItem>
                                 {
                                     new ListItem("Name", "Name"),
                                     new ListItem("Code", "Code"),
                                     new ListItem("Price", "Price"),
                                     new ListItem("Quantity", "Quantity"),
                                     new ListItem("Type", "Type"),
                                     new ListItem("Color", "Color"),
                                     new ListItem("Size", "Size"),
                                 };
            //ViewBag.SoftFields = new SelectList(softFields, Session["SoftField"]);
            ViewBag.SoftFields = new SelectList(softFields, softField);

            //apply filtering for get list product

            var filterExpressions = new Collection<Expression<Func<Product, bool>>>();

            Expression<Func<Product, bool>> expressionLeft = (product => product.IsDeleted == false);

            filterExpressions.Add(expressionLeft);

            //filter by category

            if (categoryId != null)
            {
                var category = _unitOfWork.CategoryRepository.GetByID(categoryId);
                expressionLeft = (product => product.Categories.FirstOrDefault(c => c.ID == categoryId).ID == categoryId);
                filterExpressions.Add(expressionLeft);
            }

            //filter by Ishot, IsHomepage, IsApproved, IsDiscount

            if (filter != null)
            {
                if (filter.IsHot)
                {
                    expressionLeft = (product => product.IsHot == filter.IsHot);
                    filterExpressions.Add(expressionLeft);
                }
                if (filter.IsApproved)
                {
                    expressionLeft = (product => product.IsApproved == filter.IsApproved);
                    filterExpressions.Add(expressionLeft);
                }
                if (filter.IsHomepage)
                {
                    expressionLeft = (product => product.IsHomepage == filter.IsHomepage);
                    filterExpressions.Add(expressionLeft);
                }
                if (filter.IsDiscount)
                {
                    expressionLeft = (product => product.IsDiscount == filter.IsDiscount);
                    filterExpressions.Add(expressionLeft);
                }
                if (filter.StatusID != null)
                {
                    expressionLeft = (product => product.StatusID == filter.StatusID);
                    filterExpressions.Add(expressionLeft);
                }
            }

            //ordering the result of filter

            Func<IQueryable<Product>, IOrderedQueryable<Product>> orderby = (product => product.OrderByDescending(p => p.CreatedDate));
            switch (softDir.ToUpper())
            {
                case "ASC":
                    if (softField != null && !string.IsNullOrEmpty(softField))
                    {
                        switch (softField)
                        {
                            case "Price":
                                orderby = (product => product.OrderBy(p => p.Price));
                                break;
                            case "Name":
                                orderby = (product => product.OrderBy(p => p.Name));
                                break;
                            case "Code":
                                orderby = (product => product.OrderBy(p => p.Code));
                                break;
                            case "Quantity":
                                orderby = (product => product.OrderBy(p => p.QuantityInStock));
                                break;
                            case "Type":
                                orderby = (product => product.OrderBy(p => p.Type));
                                break;
                            case "Size":
                                orderby = (product => product.OrderBy(p => p.Size));
                                break;
                            case "Color":
                                orderby = (product => product.OrderBy(p => p.Color));
                                break;
                            default:
                                orderby = (product => product.OrderBy(p => p.CreatedDate));
                                break;
                        }
                    }
                    break;
                case "DESC":
                    if (softField != null && !string.IsNullOrEmpty(softField))
                    {
                        switch (softField)
                        {
                            case "Price":
                                orderby = (product => product.OrderByDescending(p => p.Price));
                                break;
                            case "Name":
                                orderby = (product => product.OrderByDescending(p => p.Name));
                                break;
                            case "Code":
                                orderby = (product => product.OrderByDescending(p => p.Code));
                                break;
                            case "Quantity":
                                orderby = (product => product.OrderByDescending(p => p.QuantityInStock));
                                break;
                            case "Type":
                                orderby = (product => product.OrderByDescending(p => p.Type));
                                break;
                            case "Size":
                                orderby = (product => product.OrderByDescending(p => p.Size));
                                break;
                            case "Color":
                                orderby = (product => product.OrderByDescending(p => p.Color));
                                break;
                            default:
                                orderby = (product => product.OrderByDescending(p => p.CreatedDate));
                                break;
                        }
                    }
                    break;
            }

            //prepare to paging

            var products = _unitOfWork.ProductRepository.Get(filters: filterExpressions, orderby: orderby);

            long numberOfRecord = products.Count();

            long numberOfPage = numberOfRecord % pageSize == 0
                                   ? numberOfRecord / pageSize.Value
                                   : numberOfRecord / pageSize.Value + 1;

            ViewBag.NumberOfPage = numberOfPage;
            ViewBag.CurrentPage = pageNumber;

            products = _unitOfWork.ProductRepository.Get(filters: filterExpressions, orderby: orderby, pageSize: pageSize, pageNumber: pageNumber);
            if(viewType.ToUpper() == "LIST")
            {
                return View("ProductByList", products.ToList());
            }
            return View(products.ToList());
        }

        //
        // GET: /Product/Details/5

        public ViewResult Details(long productId)
        {
            //if (productId != null)
            //{
                //var product = _unitOfWork.ProductRepository.GetByID(id);
                var product =
                    _unitOfWork.ProductRepository.Get(p => p.ID == productId, includeProperties: "Status, Categories").
                        ToList();
                return View(product[0]);
           // }
            //else
            //    return View("Error");
        }

        [HttpGet]
        public PartialViewResult CompactDetails(long productId)
        {
            //Product product = _unitOfWork.ProductRepository.GetByID(productId);
            var product =
                    _unitOfWork.ProductRepository.Get(p => p.ID == productId, includeProperties: "Status, Categories").
                        ToList();
            return PartialView("_ProductCompactDetails",product[0]);
        }

        protected override void Dispose(bool disposing)
        {
            _unitOfWork.Dispose();
            base.Dispose(disposing);
        }
    }
}